Skip to content

test_runner: warn on test file patterns that do not exist#64345

Open
UditDewan wants to merge 1 commit into
nodejs:mainfrom
UditDewan:fix-test-runner-missing-patterns
Open

test_runner: warn on test file patterns that do not exist#64345
UditDewan wants to merge 1 commit into
nodejs:mainfrom
UditDewan:fix-test-runner-missing-patterns

Conversation

@UditDewan

@UditDewan UditDewan commented Jul 7, 2026

Copy link
Copy Markdown

Currently createTestFileList() only errors when all user-supplied patterns collectively match nothing and none of them contain glob magic. As a result, a nonexistent literal path passed alongside a matching glob is silently dropped:

node --test no-tests-here "spec/*.test.js"   # no-tests-here silently ignored
node --test "spec/*.test.js" --test-reporter tap   # trailing options parsed as patterns, silently ignored

This change adds a per-pattern check: any literal (non-glob) pattern that does not exist on disk is now reported with a process warning (Warning: Could not find '...'). The run itself is unaffected — matching patterns still execute and the exit code is unchanged — so this avoids the semver-major implications of erroring (see review discussion) while still surfacing the mistake, which is what #64109 asks for ("a warning or error should be printed").

Glob patterns that match nothing intentionally stay silent so existing workflows with optional globs keep working, and the pre-existing hard error when all patterns are literal and match nothing is preserved as-is.

Added test cases to test/parallel/test-runner-cli.js covering both repros from the issue, for both --test-isolation=none and process.

Fixes: #64109

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/test_runner

@nodejs-github-bot nodejs-github-bot added needs-ci PRs that need a full CI run. test_runner Issues and PRs related to the test runner subsystem. labels Jul 7, 2026
Comment on lines +165 to +178
if (hasUserSuppliedPattern) {
if (results.length === 0 && ArrayPrototypeEvery(glob.matchers, (m) => !m.hasMagic())) {
console.error(`Could not find '${ArrayPrototypeJoin(patterns, ', ')}'`);
process.exit(kGenericUserError);
}

const missing = ArrayPrototypeFilter(patterns, (pattern, i) => {
return !glob.matchers[i].hasMagic() && !existsSync(resolve(cwd, pattern));
});

if (missing.length > 0) {
console.error(`Could not find '${ArrayPrototypeJoin(missing, ', ')}'`);
process.exit(kGenericUserError);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (hasUserSuppliedPattern) {
if (results.length === 0 && ArrayPrototypeEvery(glob.matchers, (m) => !m.hasMagic())) {
console.error(`Could not find '${ArrayPrototypeJoin(patterns, ', ')}'`);
process.exit(kGenericUserError);
}
const missing = ArrayPrototypeFilter(patterns, (pattern, i) => {
return !glob.matchers[i].hasMagic() && !existsSync(resolve(cwd, pattern));
});
if (missing.length > 0) {
console.error(`Could not find '${ArrayPrototypeJoin(missing, ', ')}'`);
process.exit(kGenericUserError);
}
if (hasUserSuppliedPattern && results.length === 0) {
console.error(`Could not find '${ArrayPrototypeJoin(patterns, ', ')}'`);
process.exit(kGenericUserError);
}

Wouldn't this suffice?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately not — that check only fires when all patterns collectively match nothing, which is the pre-existing behavior (minus the hasMagic() guard). In the repro from #64109, spec/*.test.js does match files, so results.length > 0 and no-tests-here is still silently dropped. The per-pattern check is what catches a nonexistent literal path even when other patterns match.

I also deliberately kept the hasMagic() guard on both checks so a glob that matches zero files keeps its current no-error behavior — removing it would newly fail runs that pass optional globs. Happy to make globs error too if that's preferred, but it seemed like a separate (and riskier) behavior change.

@UditDewan UditDewan requested a review from avivkeller July 7, 2026 20:49
@atlowChemi

Copy link
Copy Markdown
Member

Not sure this is the direction proposed in nodejs/test-runner#13 but this would probably be a semver-major PRs that contain breaking changes and should be released in the next major version. anyway

Emit a warning for each literal positional argument that does not
match an existing file instead of silently dropping it. A warning
rather than an error keeps existing passing invocations passing.

Fixes: nodejs#64109
@UditDewan UditDewan force-pushed the fix-test-runner-missing-patterns branch from e2d29cb to a8895e4 Compare July 13, 2026 00:58
@UditDewan UditDewan changed the title test_runner: error on test file patterns that do not exist test_runner: warn on test file patterns that do not exist Jul 13, 2026
@UditDewan

Copy link
Copy Markdown
Author

@atlowChemi I've reworked this to emit a process warning instead of erroring, since #64109 asks for "a warning or error". Existing invocations keep their exit codes, so this should now be semver-minor, and it doesn't preclude whatever direction nodejs/test-runner#13 lands on for the broader --test parsing redesign.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-ci PRs that need a full CI run. test_runner Issues and PRs related to the test runner subsystem.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

test_runner: node --test silently drops options or args in certain cases

4 participants